/*
 *  Copyright 2011 derek.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.aocore.packet.CS;

import com.aocore.d2data.BattleNetCharacter;
import com.aocore.d2data.BattleNetClient;
import com.aocore.d2data.CharacterFlags;
import com.aocore.d2data.CharacterTitle;
import com.aocore.d2data.ChatEventType;
import com.aocore.packet.CSPacket;
import com.aocore.util.ByteConverter;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 *
 * @author derek
 */
public class ChatEvent extends CSPacket
{
    protected ChatEventType eventType;
    //TODO: cast ? can be either BattleNetCharacterFlags or ChannelFlags... Flags 1 ?
    protected int flags;
    protected int ping;
    protected String account;
    protected String name = null;
    protected String message = null;
    protected String realm = null;

    protected BattleNetClient client = BattleNetClient.Unknown;

    protected int clientVersion = -1;
    protected BattleNetCharacter characterType = BattleNetCharacter.Unknown;
    protected int characterLevel = -1;
    // Diablo II specific...
    protected CharacterFlags characterFlags = CharacterFlags.None;
    protected int characterAct = -1;
    protected CharacterTitle characterTitle = CharacterTitle.None;

    public ChatEvent(byte... data)
    {
        super(data);

        ByteBuffer byteBuffer = ByteBuffer.wrap(data);
        byteBuffer.order(ByteOrder.LITTLE_ENDIAN);
        this.eventType = ChatEventType.valueOf(byteBuffer.getInt(4));
        this.flags = byteBuffer.getInt(8);
        this.ping = byteBuffer.getInt(12);
        //TODO: unknown bits
        // (DWORD) 0	// Not really always 0 ! Flags 2 ?
        // (DWORD) ^1	// Used to be client ID. For chats, was client IP. Not used for anything specific anymore !?!
        // (DWORD) ^2	// Used to be Registration Authority. For chats, was zero. Not used anymore !?

        int index = ByteConverter.getByteOffset(data, 0, 28);
        int pos = ByteConverter.getByteOffset(data, 42, 28, index);	// 42 == '*'
        if (pos > 0)
        {
            this.name = ByteConverter.getString(data, 28, pos);
            index -= pos + 1;
            pos += 29;
        }
        else if (pos == 0)
        {
            pos = 29;
            index--;
            this.characterType = BattleNetCharacter.OpenCharacter;
        }
        else pos = 28;
        this.account = ByteConverter.getString(data, pos, index);
        index += pos + 1;

        if (this.eventType == ChatEventType.ChannelLeave)
            return;
        if (this.eventType == ChatEventType.ChannelJoin || this.eventType == ChatEventType.ChannelUser)
        {
            // Parse the stat string
            if (data.length - index > 4)
            {
                this.client = BattleNetClient.valueOf(byteBuffer.getInt(index));
                index += 4;
            }
            if (this.client == BattleNetClient.StarcraftShareware || this.client == BattleNetClient.Starcraft || this.client == BattleNetClient.StarcraftBroodWar)
            {
                //realm = account after @
            }
            else if (this.client == BattleNetClient.Diablo2 || this.client == BattleNetClient.Diablo2LoD)
            {
                if (this.client == BattleNetClient.Diablo2LoD)
                    this.characterFlags  = CharacterFlags.valueOf(this.characterFlags.getId() | CharacterFlags.Expansion.getId());

                if (data.length - index < 5) // Some chat bots don't even have a realm string...
                    return;

                this.realm = ByteConverter.getString(data, index, (byte)44); // 44 == ','
                index += this.realm.length() + 1;
                if (data.length < index)
                    return;

                // We don't need the name a second time...
                //this.name = ByteConverter.GetString(data, index, -1, 44); // 44 == ','
                //index += this.name.Length + 1;
                index += ByteConverter.getByteOffset(data, 44, index) + 1;
                if (index == -1 || data.length <= index)
                    return;

                if (data.length - index < 34) //TODO: test, get what info is available if any
                    return;

//                StatString.ParseD2StatString(data, index, //length,
//                ref this.clientVersion, ref this.characterType, ref this.characterLevel,
//                ref this.characterFlags, ref this.characterAct, ref this.characterTitle);
            }
        }
        else//if (this.eventType == ChatEventType.Broadcast || this.eventType == ChatEventType.ChannelMessage)
            this.message = ByteConverter.getString(data, index);
    }

    @Override
    public String toString()
    {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("CSPacket: ").append("ChatEvent").append("\n");
        stringBuilder.append("eventType: ").append(eventType).append("\n");
        stringBuilder.append("flags: ").append(flags).append("\n");
        stringBuilder.append("ping: ").append(ping).append("\n");
        stringBuilder.append("account: ").append(account).append("\n");
        stringBuilder.append("name: ").append(name).append("\n");
        stringBuilder.append("message: ").append(message).append("\n");
        stringBuilder.append("realm: ").append(realm).append("\n");
        stringBuilder.append("client: ").append(client).append("\n");
        stringBuilder.append("clientVersion: ").append(clientVersion).append("\n");
        stringBuilder.append("characterType: ").append(characterType).append("\n");
        stringBuilder.append("characterLevel: ").append(characterLevel).append("\n");
        stringBuilder.append("characterFlags: ").append(characterFlags).append("\n");
        stringBuilder.append("characterAct: ").append(characterAct).append("\n");
        stringBuilder.append("characterTitle: ").append(characterTitle).append("\n");
        return stringBuilder.toString();
    }
}
